/**
 * Licensed under GNU LESSER GENERAL PUBLIC LICENSE Version 3
 * 
 * Inspired from: HTML Virtual Keyboard Interface Script - v1.11
 * http://www.greywyvern.com/code/js/keyboard.html Copyright (c) 2008 -
 * GreyWyvern Licenced for free distribution under the BSDL
 * http://www.opensource.org/licenses/bsd-license.php
 * 
 * 
 * @author Edouard Fattal <efattal@gmail.com>
 * @url http://efattal.fr/extjs/examples/virtualkeyboard
 */

/**
 * @class Ext.ux.VirtualKeyboard
 * @extends Ext.Component
 */
Ext.define("AmpleHarvest.addOns.keyboard.test.cKeyboard",
{
	extend				: "Ext.panel.Panel",
	requires			:
	[
			"Ext.core.DomHelper", "AmpleHarvest.addOns.keyboard.cKey",
			"Ext.form.field.ComboBox"
	],
	uses				:
	[
			'Ext.form.field.ComboBox', 'Ext.data.Store',

			'AmpleHarvest.addOns.keyboard.layout.English_US',
			'AmpleHarvest.addOns.keyboard.layout.Cyrillic_RU'
	],
	statics				:
	{
		C_STR_EVENT_CAPS	: "presscapslock",
		C_STR_EVENT_SHIFT	: "pressshift"
	},

	/* ***** Create keyboards **************************************** */
	keyboardTarget		: null,
	alias				: 'widget.virtualkeyboard',
	languageSelection	: false,
	numpad				: true,
	keyCenter			: 3,
	layoutDDK			: {},
	shift				: false,
	capslock			: false,
	alternate			: false,
	dead				: false,
	deadKeysOn			: false,
	m_arr_Language		: [],
	deadKey				:
	{
		'"'			:
		[ // Umlaut / Diaeresis / Greek Dialytika
				[
						"a", "\u00e4"
				],
				[
						"e", "\u00eb"
				],
				[
						"i", "\u00ef"
				],
				[
						"o", "\u00f6"
				],
				[
						"u", "\u00fc"
				],
				[
						"y", "\u00ff"
				],
				[
						"\u03b9", "\u03ca"
				],
				[
						"\u03c5", "\u03cb"
				],
				[
						"A", "\u00c4"
				],
				[
						"E", "\u00cb"
				],
				[
						"I", "\u00cf"
				],
				[
						"O", "\u00d6"
				],
				[
						"U", "\u00dc"
				],
				[
						"Y", "\u0178"
				],
				[
						"\u0399", "\u03aa"
				],
				[
						"\u03a5", "\u03ab"
				]
		],
		'\u00a8'	:
		[ // Umlaut / Diaeresis / Greek Dialytika
				[
						"a", "\u00e4"
				],
				[
						"e", "\u00eb"
				],
				[
						"i", "\u00ef"
				],
				[
						"o", "\u00f6"
				],
				[
						"u", "\u00fc"
				],
				[
						"y", "\u00ff"
				],
				[
						"\u03b9", "\u03ca"
				],
				[
						"\u03c5", "\u03cb"
				],
				[
						"A", "\u00c4"
				],
				[
						"E", "\u00cb"
				],
				[
						"I", "\u00cf"
				],
				[
						"O", "\u00d6"
				],
				[
						"U", "\u00dc"
				],
				[
						"Y", "\u0178"
				],
				[
						"\u0399", "\u03aa"
				],
				[
						"\u03a5", "\u03ab"
				]
		],
		'~'			:
		[ // Tilde
				[
						"a", "\u00e3"
				],
				[
						"o", "\u00f5"
				],
				[
						"n", "\u00f1"
				],
				[
						"A", "\u00c3"
				],
				[
						"O", "\u00d5"
				],
				[
						"N", "\u00d1"
				]
		],
		'^'			:
		[ // Circumflex
				[
						"a", "\u00e2"
				],
				[
						"e", "\u00ea"
				],
				[
						"i", "\u00ee"
				],
				[
						"o", "\u00f4"
				],
				[
						"u", "\u00fb"
				],
				[
						"w", "\u0175"
				],
				[
						"y", "\u0177"
				],
				[
						"A", "\u00c2"
				],
				[
						"E", "\u00ca"
				],
				[
						"I", "\u00ce"
				],
				[
						"O", "\u00d4"
				],
				[
						"U", "\u00db"
				],
				[
						"W", "\u0174"
				],
				[
						"Y", "\u0176"
				]
		],
		'\u02c7'	:
		[ // Baltic caron
				[
						"c", "\u010D"
				],
				[
						"s", "\u0161"
				],
				[
						"z", "\u017E"
				],
				[
						"r", "\u0159"
				],
				[
						"d", "\u010f"
				],
				[
						"t", "\u0165"
				],
				[
						"n", "\u0148"
				],
				[
						"l", "\u013e"
				],
				[
						"e", "\u011b"
				],
				[
						"C", "\u010C"
				],
				[
						"S", "\u0160"
				],
				[
						"Z", "\u017D"
				],
				[
						"R", "\u0158"
				],
				[
						"D", "\u010e"
				],
				[
						"T", "\u0164"
				],
				[
						"N", "\u0147"
				],
				[
						"L", "\u013d"
				],
				[
						"E", "\u011a"
				]
		],
		'\u02d8'	:
		[ // Romanian and Turkish breve
				[
						"a", "\u0103"
				],
				[
						"g", "\u011f"
				],
				[
						"A", "\u0102"
				],
				[
						"G", "\u011e"
				]
		],
		'`'			:
		[ // Grave
				[
						"a", "\u00e0"
				],
				[
						"e", "\u00e8"
				],
				[
						"i", "\u00ec"
				],
				[
						"o", "\u00f2"
				],
				[
						"u", "\u00f9"
				],
				[
						"A", "\u00c0"
				],
				[
						"E", "\u00c8"
				],
				[
						"I", "\u00cc"
				],
				[
						"O", "\u00d2"
				],
				[
						"U", "\u00d9"
				]
		],
		"'"			:
		[ // Acute / Greek Tonos
				[
						"a", "\u00e1"
				],
				[
						"e", "\u00e9"
				],
				[
						"i", "\u00ed"
				],
				[
						"o", "\u00f3"
				],
				[
						"u", "\u00fa"
				],
				[
						"\u03b1", "\u03ac"
				],
				[
						"\u03b5", "\u03ad"
				],
				[
						"\u03b7", "\u03ae"
				],
				[
						"\u03b9", "\u03af"
				],
				[
						"\u03bf", "\u03cc"
				],
				[
						"\u03c5", "\u03cd"
				],
				[
						"\u03c9", "\u03ce"
				],
				[
						"A", "\u00c1"
				],
				[
						"E", "\u00c9"
				],
				[
						"I", "\u00cd"
				],
				[
						"O", "\u00d3"
				],
				[
						"U", "\u00da"
				],
				[
						"\u0391", "\u0386"
				],
				[
						"\u0395", "\u0388"
				],
				[
						"\u0397", "\u0389"
				],
				[
						"\u0399", "\u038a"
				],
				[
						"\u039f", "\u038c"
				],
				[
						"\u03a5", "\u038e"
				],
				[
						"\u03a9", "\u038f"
				]
		],
		'\u00b4'	:
		[ // Acute / Greek Tonos
				[
						"a", "\u00e1"
				],
				[
						"e", "\u00e9"
				],
				[
						"i", "\u00ed"
				],
				[
						"o", "\u00f3"
				],
				[
						"u", "\u00fa"
				],
				[
						"\u03b1", "\u03ac"
				],
				[
						"\u03b5", "\u03ad"
				],
				[
						"\u03b7", "\u03ae"
				],
				[
						"\u03b9", "\u03af"
				],
				[
						"\u03bf", "\u03cc"
				],
				[
						"\u03c5", "\u03cd"
				],
				[
						"\u03c9", "\u03ce"
				],
				[
						"A", "\u00c1"
				],
				[
						"E", "\u00c9"
				],
				[
						"I", "\u00cd"
				],
				[
						"O", "\u00d3"
				],
				[
						"U", "\u00da"
				],
				[
						"\u0391", "\u0386"
				],
				[
						"\u0395", "\u0388"
				],
				[
						"\u0397", "\u0389"
				],
				[
						"\u0399", "\u038a"
				],
				[
						"\u039f", "\u038c"
				],
				[
						"\u03a5", "\u038e"
				],
				[
						"\u03a9", "\u038f"
				]
		],
		'\u0384'	:
		[ // Acute / Greek Tonos
				[
						"a", "\u00e1"
				],
				[
						"e", "\u00e9"
				],
				[
						"i", "\u00ed"
				],
				[
						"o", "\u00f3"
				],
				[
						"u", "\u00fa"
				],
				[
						"\u03b1", "\u03ac"
				],
				[
						"\u03b5", "\u03ad"
				],
				[
						"\u03b7", "\u03ae"
				],
				[
						"\u03b9", "\u03af"
				],
				[
						"\u03bf", "\u03cc"
				],
				[
						"\u03c5", "\u03cd"
				],
				[
						"\u03c9", "\u03ce"
				],
				[
						"A", "\u00c1"
				],
				[
						"E", "\u00c9"
				],
				[
						"I", "\u00cd"
				],
				[
						"O", "\u00d3"
				],
				[
						"U", "\u00da"
				],
				[
						"\u0391", "\u0386"
				],
				[
						"\u0395", "\u0388"
				],
				[
						"\u0397", "\u0389"
				],
				[
						"\u0399", "\u038a"
				],
				[
						"\u039f", "\u038c"
				],
				[
						"\u03a5", "\u038e"
				],
				[
						"\u03a9", "\u038f"
				]
		],
		'\u02dd'	:
		[ // Hungarian Double Acute Accent
				[
						"o", "\u0151"
				],
				[
						"u", "\u0171"
				],
				[
						"O", "\u0150"
				],
				[
						"U", "\u0170"
				]
		],
		'\u0385'	:
		[ // Greek Dialytika + Tonos
				[
						"\u03b9", "\u0390"
				],
				[
						"\u03c5", "\u03b0"
				]
		],
		'\u00b0'	:
		[ // Ring
				[
						"a", "\u00e5"
				],
				[
						"A", "\u00c5"
				]
		],
		'\u00ba'	:
		[ // Ring
				[
						"a", "\u00e5"
				],
				[
						"A", "\u00c5"
				]
		]
	},

	initComponent		: function(options)
	{
		this.callParent();

		this.m_arr_Language[AmpleHarvest.addOns.keyboard.layout.Cyrillic_RU.C_STR_NAME] = Ext
				.create('AmpleHarvest.addOns.keyboard.layout.Cyrillic_RU');
		this.m_arr_Language[AmpleHarvest.addOns.keyboard.layout.English_US.C_STR_NAME] = Ext
				.create('AmpleHarvest.addOns.keyboard.layout.English_US');

		Ext.apply(this,
				{
					language			: this.language || 'US',
					deadKeysButtonText	: this.deadKeysButtonText
							|| 'Type accented letters',
					// deadKeysButtonTip: this.deadKeysButtonTip || 'Dead keys
					// are used
					// to generate accented letters',
					autoDestroy			: true
				});

		if (!this.m_arr_Language[this.language])
		{
			this.language = this.m_arr_Language[AmpleHarvest.addOns.keyboard.layout.English_US.C_STR_NAME]
					.get_Language();
		}

		Ext.apply(this, options);

		this.create_Toolbar();
		this.create_Keyboard();

		this.addEvents('keypress');

		this.addEvents(this.self.C_STR_EVENT_CAPS, this.self.C_STR_EVENT_SHIFT);

		// Button Events

		this.on(this.self.C_STR_EVENT_CAPS, this.pressCapsLock, this);
		this.on(this.self.C_STR_EVENT_SHIFT, this.pressShift, this);

		/*
		 * this.on('beforedestroy', function(){
		 * this.keyboard.removeAllListeners(); delete this.keyboard; }, this);
		 */

	},

	create_Toolbar		: function()
	{
		this.m_obj_Toolbar = Ext.create("Ext.toolbar.Toolbar",
				{
					height	: 30
				});
		this.addDocked(this.m_obj_Toolbar);
		// var layouts = 0;
		// for (lang in this.Languages)
		// if (typeof this.Languages[lang] == "object")
		// layouts++;

		if (this.languageSelection)
		{
			this.m_obj_LangStore = Ext.create('Ext.data.Store',
					{
						fields	:
						[
								'label', 'data'
						]
					});
			// var values = [];
			for (str_Lang in this.m_arr_Language)
			{
				if (typeof this.m_arr_Language[str_Lang] == "object")
				{
					this.m_obj_LangStore.add(
							{
								"label"	: str_Lang,
								"data"	: str_Lang
							});
				}
			}
			//			
			// var obj_LangStore = Ext.create('Ext.data.Store',
			// {
			// fields : ['label', 'data'],
			// data : values
			// });
			//
			this.languageSelector = Ext.create("Ext.form.field.ComboBox",
					{
						store			: this.m_obj_LangStore,
						displayField	: 'label',
						queryMode		: 'local',
						valueField		: 'data',
						forceSelection	: true,
						triggerAction	: 'all',
						editable		: true,
						readOnly		: false,
						height			: 15,
						width			: 100,
						value			: this.language,
						listeners		:
						{
							'select'	: function(obj_Combo, obj_Record)
							{
								this.language = obj_Combo.getValue();
								this.buildKeys();
							},
							expand		: function()
							{
								this.selectingLanguage = true;
							},
							collapse	: function()
							{
								this.selectingLanguage = false;
							},
							scope		: this
						}
					});
			// //this.languageSelector.on("select",function(){alert("Test
			// Select")});
			// ktbarItems.push(this.languageSelector);
			this.m_obj_Toolbar.add(this.languageSelector);
		}
		else
		{
			this.m_obj_Toolbar.add(
					{
						text	: this.language
					});
		}

		// this.m_obj_Toolbar.add(
		// {
		// text : "test12345"
		// });

		// this.m_obj_Keyboard.setStyle({width: this.width || 370});

	},

	create_Keyboard		: function()
	{
		this.buildKeys();
	},

	onRender			: function(ct, position)
	{
		// this.initKeyboard(ct);
		this.callParent(arguments);
	},

	getTBar				: function()
	{
		return this.ktbar;
	},

	buildKeys			: function()
	{
		this.shift = this.capslock = this.alternate = this.dead = false;
		// this.deadKeysOn = (this.layoutDDK[this.language]) ? false :
		// this.deadCheckbox.checked;

		this.removeAll();

		var dh = Ext.core.DomHelper;

		for (var x = 0, hasdeadKey = false, lyt; lyt = this.m_arr_Language[this.language]
				.getRow(x++);)
		{
			var obj_Row = Ext.create("Ext.panel.Panel",
					{
						height	: 25,
						layout	:
						{
							type	: 'hbox',
							align	: 'stretch'
						}
					});
			this.add(obj_Row);
			for (var y = 0, lkey; lkey = lyt[y++];)
			{
				var obj_Button;
				var int_Flex = 1;
				switch (lkey[1])
				{
					case "Caps" :
					case "Shift" :
					case "Alt" :
					case "AltGr" :
					case "Tab" :
					case "Bksp" :
					case "Enter" :
						int_Flex = 3;

				}

				if (lkey[0] == " ")
				{
					int_Flex = 9;
				}

				if (!this.layoutDDK[this.language] && !hasdeadKey)
				{
					for (var z = 0; z < lkey.length; z++)
					{
						if (this.deadKey[lkey[z]])
						{
							hasdeadKey = true;
							break;
						}
					}
				}

				var alive = false;
				if (this.deadKeysOn)
				{
					for (key in this.deadKey)
					{
						if (key === lkey[0])
						{
							alive = true;
						}
					}
				}
				// var cls = ['x-btn', 'x-btn-center'];
				var cls = [];
				if (alive)
					cls.push('alive');
				if (lyt.length > this.keyCenter && y == lyt.length)
					cls.push('last');

				obj_Button = Ext.create("AmpleHarvest.addOns.keyboard.cKey",
						{
							// id : lkey[0] == " " ? "spacebar" : "",
							// html : lkey[0] == " " ? "&nbsp;" : lkey[0],
							flex	: int_Flex
						});
				// obj_Button.value = lkey[0] == " " ? "&nbsp;" : lkey[0];

				// alert(lkey[0]);
				obj_Button.set_LowerCase(lkey[0]);
				obj_Button.set_UpperCase(lkey[1]);
				obj_Button.set_Alt = (lkey[2]);
				obj_Button.set_AltShift(lkey[3]);

				obj_Row.add(obj_Button);

				obj_Button.showLower();
				obj_Button.forceUpdate();

				obj_Button.modifier = lkey[1];

				switch (lkey[1])
				{
					case "Caps" :
						obj_Button.on('click', function(obj_This, obj_Event,
										obj_Options)
								{
									this.fireEvent(this.self.C_STR_EVENT_CAPS,
											obj_This
									);
									obj_Event.stopEvent();
								}, this);
						break;
					case "Shift" :
						obj_Button.on('click', function(obj_This, obj_Event,
										obj_Options)
								{
									this.fireEvent(this.self.C_STR_EVENT_SHIFT,
											obj_This
									);
									obj_Event.stopEvent();
								}, this);
						break;
					case "Alt" :
					case "AltGr" :
						obj_Button.on('click', function(obj_This, obj_Event,
										obj_Options)
								{
									this.keyModify(obj_This.modifier);
									obj_Event.stopEvent();
								}, this);
						break;
					case "Tab" :
						obj_Button.on('click', function(event, target)
								{
									this.keyInsert("\t");
									obj_Event.stopEvent();
								}, this);
						break;
					case "Bksp" :
						obj_Button.on('click', function(obj_This, obj_Event,
										obj_Options)
								{
									var obj_DOM = this.keyboardTarget.inputEl.dom;
									var int_TxtLen = obj_DOM.selectionStart;
									if (obj_DOM.setSelectionRange)
									{
										var srt = obj_DOM.selectionStart;
										var len = obj_DOM.selectionEnd;
										// alert(srt);
										if (srt < len)
											srt++;
										// dom.value="hello world";
										obj_DOM.value = obj_DOM.value.substr(0,
												srt - 1
										)
												+ obj_DOM.value.substr(len);
										// this.keyboardTarget.setValue(dom.value.substr(0,
										// srt - 1) + dom.value.substr(len));

										obj_DOM.setSelectionRange(srt - 1, srt
														- 1);
									}
									else if (obj_DOM.createTextRange)
									{
										try
										{
											this.range.select();
										}
										catch (e)
										{
										}
										this.range = document.selection
												.createRange();
										if (!this.range.text.length)
											this.range.moveStart('character',
													-1
											);
										this.range.text = "";
									}
									else
										this.keyboardTarget
												.setValue(obj_DOM.value.substr(
														0, obj_DOM.value.length
																- 1
												));

									if (this.shift)
									{
										this.fireEvent(
												this.self.C_STR_EVENT_SHIFT,
												null
										);
									}
									if (this.alternate)
										this.keyModify("AltGr");

									this.keyboardTarget.selectText(int_TxtLen
													+ 1, int_TxtLen + 1);
									obj_Event.stopEvent();
									return true;
								}, this
						);
						break;

					case "Enter" :
						// if (self.keyboardTarget.nodeName == "TEXTAREA") {
						// this.keyInsert("\n"); } else self.VKI_close();
						obj_Button.on('click', function(event, target)
								{
									this.keyInsert("\n");
									obj_Event.stopEvent();
								}, this);
						break;

					default :
						obj_Button.on('click', function(obj_This, obj_Event,
								obj_Options)
						{
							var keyValue = obj_This.value;
							if (keyValue == "\xa0")
							{
								keyValue = " ";
							}
							if (this.deadKeysOn && this.dead)
							{
								if (this.dead != keyValue)
								{
									for (key in this.deadKey)
									{
										if (key == this.dead)
										{
											if (keyValue != " ")
											{
												for (var z = 0, rezzed = false, dk; dk = this.deadKey[key][z++];)
												{
													if (dk[0] == keyValue)
													{
														this.keyInsert(dk[1]);
														rezzed = true;
														break;
													}
												}
											}
											else
											{
												this.keyInsert(this.dead);
												rezzed = true;
											}
											break;
										}
									}
								}
								else
									rezzed = true;
							}
							this.dead = false;

							if (!rezzed && keyValue != "\xa0")
							{
								if (this.deadKeysOn)
								{
									for (key in this.deadKey)
									{
										if (key == keyValue)
										{
											this.dead = key;
											this.className = "dead";
											if (this.shift)
											{
												this
														.fireEvent(
																this.self.C_STR_EVENT_SHIFT,
																null
														);
											}
											if (this.alternate)
												this.keyModify("AltGr");
											break;
										}
									}
									if (!this.dead)
										this.keyInsert(keyValue);
								}
								else
								{
									this.keyInsert(keyValue);
								}
							}
							this.keyModify("");
							obj_Event.stopEvent();
						}, this
						);
				}
				for (var z = lkey.length; z < 4; z++)
					lkey[z] = "\xa0";
			}
		}
	},

	pressCapsLock		: function(obj_Button)
	{
		obj_Button.toggle();
		this.capslock = !this.capslock;

		var str_Output = "upper"

		if (this.capslock)
		{
			if (this.shift)
			{
				str_Output = "lower";
			}
			else
			{
				str_Output = "upper";
			}
		}
		else
		{
			if (this.shift)
			{
				str_Output = "upper";
			}
			else
			{
				str_Output = "lower";
			}
		}

		this.items.each(function(obj_Item, int_index, int_Length)
				{
					obj_Item.items.each(function(obj_Item, int_index,
									int_Length)
							{
								if (str_Output == "upper")
								{
									obj_Item.showUpper();
								}
								else
								// if (str_Output == "lower")
								{
									obj_Item.showLower();
								}
							}, this);
				}, this);
	},

	pressShift			: function(obj_Button)
	{
		if (obj_Button)
		{
			this.m_obj_CurShift = obj_Button;
		}
		else
		{
			obj_Button = this.m_obj_CurShift;
		}
		obj_Button.toggle();
		this.shift = !this.shift;

		var str_Output = "upper"

		if (this.capslock)
		{
			if (this.shift)
			{
				str_Output = "lower";
			}
			else
			{
				str_Output = "upper";
			}
		}
		else
		{
			if (this.shift)
			{
				str_Output = "upper";
			}
			else
			{
				str_Output = "lower";
			}
		}

		this.items.each(function(obj_Item, int_index, int_Length)
				{
					obj_Item.items.each(function(obj_Item, int_index,
									int_Length)
							{
								if (str_Output == "upper")
								{
									obj_Item.showUpper();
								}
								else
								// if (str_Output == "lower")
								{
									obj_Item.showLower();
								}
							}, this);
				}, this);
	},

	keyModify			: function(type)
	{
		switch (type)
		{
			case "Alt" :
			case "AltGr" :
				this.alternate = !this.alternate;
				break;
			case "Caps" :
				this.capslock = !this.capslock;
				break;
			case "Shift" :
				this.shift = !this.shift;
				break;
		}
		var vchar = 0;
		if (!this.shift != !this.capslock)
			vchar += 1;

		if (!this.Languages[this.language])
		{
			return false;
		}
		for (var x = 0; x < this.items.getCount(); x++)
		{
			var obj_Row = this.items.getAt(x);

			if (!this.Languages[this.language][x])
			{
				continue;
			}
			for (var y = 0; y < obj_Row.items.getCount(); y++)
			{
				if (!this.Languages[this.language][x][y])
				{
					continue;
				}

				var lkey = this.Languages[this.language][x][y];
				var obj_Button = obj_Row.items.getAt(y);

				switch (lkey[1])
				{
					case "Alt" :
					case "AltGr" :
						if (this.alternate)
							dead = true;
						break;
					case "Shift" :
						if (this.shift)
							dead = true;
						break;
					case "Caps" :
						if (this.capslock)
							dead = true;
						break;
					case "Tab" :
					case "Enter" :
					case "Bksp" :
						break;
					default :
						var char = lkey[vchar
								+ ((this.alternate && lkey.length == 4) ? 2 : 0)];
						if (type)
							obj_Button.update(char);
						if (this.deadKeysOn)
						{
							if (this.dead)
							{
								if (char == this.dead)
									dead = true;
								for (var z = 0; z < this.deadKey[this.dead].length; z++)
								{
									if (char == this.deadKey[this.dead][z][0])
									{
										isTarget = true;
										break;
									}
								}
							}
							for (key in this.deadKey)
							{
								if (key === char)
								{
									alive = true;
									break;
								}
							}
						}
				}
			}
		}
	},

	keyInsert			: function(keyValue)
	{
		this.fireEvent('keyPress', this, keyValue);

		if (this.keyboardTarget)
		{
			var obj_DOM = this.keyboardTarget.inputEl.dom;

			var int_TxtLen = obj_DOM.selectionEnd;

			if (obj_DOM.setSelectionRange)
			{
				var int_Start = obj_DOM.selectionStart;
				var int_Len = obj_DOM.selectionEnd;
				obj_DOM.value = obj_DOM.value.substr(0, int_Start) + keyValue
						+ obj_DOM.value.substr(int_Len);
				if (keyValue == "\n" && window.opera)
				{
					int_Start++;
				}
				obj_DOM.setSelectionRange(int_Start + keyValue.length,
						int_Start + keyValue.length
				);
			}
			else if (obj_DOM.createTextRange)
			{
				try
				{
					this.range.select();
				}
				catch (e)
				{
				}
				this.range = document.selection.createRange();
				this.range.text = keyValue;
				this.range.collapse(true);
				this.range.select();
			}
			else
			{
				this.keyboardTarget.setValue(this.keyboardTarget.getValue()
						+ keyValue);
			}

			if (this.shift)
			{
				this.fireEvent(this.self.C_STR_EVENT_SHIFT, null);
			}
			if (this.alternate)
				this.keyModify("AltGr");

			this.keyboardTarget.focus();
			this.keyboardTarget.selectText(int_TxtLen + 1, int_TxtLen + 1);
		}
	},

	getXType			: function()
	{
		return 'virtualkeyboard';
	},

	IESel				: function(event, target)
	{
		if (target.createTextRange)
		{
			this.range = document.selection.createRange();
		}
	}
}
);
